import cgi

import os

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.ext.db import djangoforms
import my_geopt
import base64
from django.core.paginator import ObjectPaginator, InvalidPage

from google.appengine.api import images

# http://189.65.183.9:8080/
#API_KEY = 'ABQIAAAAul_IdOn_eu47kED1sycOnRQJJhtmVC2XqQ0kEf_OejgoybTNhhQJGiPSplMKwJpLA033u-4YkgZXjA'
# http://192.168.1.217:8080
#API_KEY = 'ABQIAAAAul_IdOn_eu47kED1sycOnRS7UKXLwH3zczRi8i4P75GbVoqZ_hRFva8ExfPaJ7wAK1NpT5jL8SbakQ'
# http://eallert.appspot.com
API_KEY='ABQIAAAAul_IdOn_eu47kED1sycOnRQzftoObCXTK332nx8d4BnhbxASphT6N34fPZBPMhRtt7M4nBsY4GyedA'

CATEGORY_CHOICES = (
    'Lost',
    'Accident',
    'Road block',
    'Earthquake',
    'Eruption',
    'Extreme heat',
    'Floods',
    'Hurricanes',
    'Landslide',
    'Tornadoes',
    'Tsunamis',
    'Volcanoes',
    'Wildfire',
    'Winter storm',
    'Snow',
    'Attack',
    'Hunger',
  )

SPECIAL_CARE_CHOICES = (
    'Cancer',
    'Deafness',
    'Diabetes',
    'Disabilities',
    'Blood Disordes',
    'High Blood Pressure',
  )

DEFAULT_WIDTH = 300
DEFAULT_HEIGHT = 300

my_geopt.width = DEFAULT_WIDTH
my_geopt.height = DEFAULT_HEIGHT

class Allert(db.Model):
    sender = db.UserProperty()
    description = db.StringProperty(multiline=True)
    contact = db.StringProperty()
    picture = db.BlobProperty()
    thumb = db.BlobProperty()
    geo_pos = db.GeoPtProperty()
    category = db.StringProperty(choices=CATEGORY_CHOICES)
    specialcare = db.StringProperty(choices=SPECIAL_CARE_CHOICES)
    date = db.DateTimeProperty(auto_now_add=True)

class AllertForm(djangoforms.ModelForm):
    class Meta:
        model = Allert
        exclude = ("creationDate","picture") 

class MainPage(webapp.RequestHandler):
    def get(self):
        allert_list = db.GqlQuery("SELECT * FROM Allert ORDER BY date DESC")

        paginator = ObjectPaginator(allert_list, 5) # Show 5 contributions per page
        
        # Make sure page request is an int. If not, deliver first page.
        try:
            page = int(self.request.GET.get('page', '0'))
        except ValueError:
            page = 0
            
        # If page request  is out of range, deliver last page of results.
        try:
            records = paginator.get_page(page)
            page_number = page
            next_page = page + 1
            if page > 0:
                previous_page = page - 1
            else:
                previous_page = 0
        except (InvalidPage):
            records = paginator.get_page(paginator.pages)
            page_number = paginator.pages
            next_page = paginator.pages
            previous_page = paginator.pages - 1
      
        path = getTemplatePath(self.request)
        contents = {'API_KEY':API_KEY,
                    'width':DEFAULT_WIDTH,'height':DEFAULT_HEIGHT,
                    'form': AllertForm(),
                    'allert_list': records,
                    'has_previous': paginator.has_previous_page(page_number),
                    'has_next': paginator.has_next_page(page_number),
                    'next_page':next_page,
                    'previous_page':previous_page,
                    'num_pages':paginator.pages,
                    'page_number':page_number+1}
        self.response.out.write(template.render(path, contents))

def getTokens(src_str, token_list):
    res_list = []
    if token_list:
        for i in src_str.split(token_list[0]):
            for j in getTokens(i, token_list[1:]):
                res_list.append(j)
        return res_list
    else:
        return [src_str]

def deviceCategory(request):
    '''
    Return the best match for the request as a mobile or desktop device.
    
    Using the headers off the request try to guess if its a small device 
    or a computer device, returns a character ('d','m') representing the
    best match for the header, without using a database or a big file with
    all the possible headers.
    '''
    heuristic = ('nokia','ericson',
      's60',
      'samsung',
      'motorola',
      'lg',
      'sony',
      'siemens',
      'gradiente',
      'iphone',
      'midp',
      'symbian',
      'symbianos',
      'foston',
      'htc',
      'sharp',
      'aiko',
      'panasonic',
      'alcatel',
      'pantec',
      'blackberry',)    

    l = getTokens(request.user_agent.lower(),';/. ()')

    count = 0
    for token in l:
        if token in heuristic:
            count += 1
    
    if count > 0:
        # Mobile
        device = 'm'
    else:
        # Desktop
        device = 'd'
        
    return device

def getTemplatePath(request, type='index'):
    # Try to guess if it is a mobile device or a
    # Desktop/Computer device.
    device = deviceCategory(request)
    dir_name = '%s/templates' % os.path.dirname(__file__)
    path = {
      'map': os.path.join(dir_name, 'map_simple%s.html'%device),
      'index': os.path.join(dir_name, 'index%s.html'%device),
      'allert': os.path.join(dir_name, 'allert%s.html'%device),
      'img': os.path.join(dir_name, 'img_simple.html'),
    }
    
    return path[type]

class GetMap(webapp.RequestHandler):
    def get(self):
        key = self.request.get('k')
        allert = getAllert(key)

        if (allert and allert.geo_pos):
            tmpl_path = getTemplatePath(self.request,type='map')
            contents = {'API_KEY':API_KEY,
                        'info': allert.description.split('\n')[0],
                        'width':DEFAULT_WIDTH,'height':DEFAULT_HEIGHT,
                        'lat': allert.geo_pos.lat,
                        'lon': allert.geo_pos.lon}
            self.response.out.write(template.render(tmpl_path, contents))
        else:
            self.error(404)

class ViewImage(webapp.RequestHandler):
    def get(self):
        key = self.request.get('k')
        allert = getAllert(key)

        if (allert and allert.picture):
            tmpl_path = getTemplatePath(self.request,type='img')
            contents = {'API_KEY':API_KEY,
                        'allert': allert,
                        'width':DEFAULT_WIDTH,'height':DEFAULT_HEIGHT,
                        }
            self.response.out.write(template.render(tmpl_path, contents))
        else:
            self.error(404)

class GetThumb(webapp.RequestHandler):
    def get(self):
        key = self.request.get('k')
        allert = getAllert(key)

        if (allert and allert.thumb):
           self.response.headers['Content-Type'] = 'image/jpg'
           self.response.out.write(allert.thumb)
        else:
           self.redirect('/static/noimage.jpg')


class GetImage(webapp.RequestHandler):
    def get(self):
        key = self.request.get('k')
        allert = getAllert(key)

        if (allert and allert.picture):
           self.response.headers['Content-Type'] = 'image/jpg'
           self.response.out.write(allert.picture)
        else:
           self.redirect('/static/noimage.jpg')

def getAllert(key):
    result = db.get(key)
    if result:
        return result
    else:
        return None
 
class Allerthandler(webapp.RequestHandler):
    def post(self):
        data = AllertForm(data=self.request.POST)
        if data.is_valid():
            if users.get_current_user():
                allert.author = users.get_current_user()
            # Save the data, and redirect to the view page
            picture = self.request.get("img")
            allert = data.save(commit=False)
            if isinstance(picture, unicode):
                picture = base64.decodestring(picture)
            allert.picture = db.Blob(picture)
            thumb = images.Image(picture)
            thumb.resize(42, 42)
            thumb.im_feeling_lucky()
            allert.thumb = db.Blob(thumb.execute_transforms(output_encoding=images.JPEG))
            allert.put()
            self.redirect('/')
        else:
            # Reprint the form
            contents = {'API_KEY':API_KEY,
                        'width':DEFAULT_WIDTH,'height':DEFAULT_HEIGHT,
                        'form': data}
            path = getTemplatePath(self.request)
            self.response.out.write(template.render(path, contents))
            #self.response.out.write(data)
            #self.response.out.write(self.request.POST)
    
    def get(self):
        key = self.request.get('k')
        allert = getAllert(key)

        if (allert):
            tmpl_path = getTemplatePath(self.request,type='allert')
            contents = {'API_KEY':API_KEY,
                        'allert': allert,
                        'width':DEFAULT_WIDTH,'height':DEFAULT_HEIGHT,
                        'lat': allert.geo_pos.lat,
                        'lon': allert.geo_pos.lon
                        }
            self.response.out.write(template.render(tmpl_path, contents))
        else:
            self.error(404)

class Agent(webapp.RequestHandler):
    def get(self):
        self.response.out.write(self.request.user_agent)

class ResetCategory(webapp.RequestHandler):
    def get(self):
        allert_list = Allert.all()
        for allert in allert_list:
            allert.category = 'Lost'
            allert.specialcare = 'Disabilities'
            allert.put
        self.response.out.write("OK.")
        
application = webapp.WSGIApplication(
                                     [('/agent',Agent),('/', MainPage),
                                      ('/thumb', GetThumb),
                                      ('/pic', GetImage),
                                      ('/pic_view', ViewImage),
                                      ('/map', GetMap),
                                      ('/reset', ResetCategory),
                                      ('/allert', Allerthandler)],
                                     debug=True)

    
def main():
    run_wsgi_app(application)

if __name__ == '__main__':
    main()

